package cn.shanguoyu.base.springboot.starter.limit.aop;

import cn.shanguoyu.base.springboot.starter.convention.errorcode.ClientErrorCode;
import cn.shanguoyu.base.springboot.starter.convention.exception.ClientException;
import cn.shanguoyu.base.springboot.starter.convention.exception.QuickThrow;
import cn.shanguoyu.base.springboot.starter.limit.manager.abs.LimiterManager;
import cn.shanguoyu.base.springboot.starter.limit.manager.pojo.Limiter;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * @description:限流切面
 * @author：sgy
 * @date: 2023-05-29
 */
@Aspect
@Slf4j
@AllArgsConstructor
public class LimitAspect {
    private final LimiterManager limiterManager;

    /**
     * 使用AOP在方法之前拦截请求，只拦标注了limitPointAnnotation的类
     *
     * @param limitAnnotation
     */
    @Before("@annotation(limitAnnotation)")
    public void interceptor(RateLimiter limitAnnotation) {
        Limiter limiter = Limiter.builder()
                .key(limitAnnotation.key())
                .permitsPerSecond(limitAnnotation.permitsPerSecond())
                .period(limitAnnotation.period())
                .limit(limitAnnotation.limit())
                .timeout(limitAnnotation.timeout())
                .timeUnit(limitAnnotation.timeUnit())
                .limitType(limitAnnotation.limitType())
                .prefix(limitAnnotation.prefix())
                .build();
        boolean b = limiterManager.tryAccess(limiter);
        if (!b) {
            QuickThrow.throwException(new ClientException(ClientErrorCode.LIMIT_ERROR));
        }
    }
}
